import { getStorage } from '$lib/utils/stores'
import axios, {
  type AxiosInstance,
  type AxiosRequestConfig,
  type AxiosResponse,
  type InternalAxiosRequestConfig,
  AxiosError,
  type AxiosRequestHeaders,
} from 'axios'


import type { ResponseData } from '$lib/api/types'

// 扩展请求配置
interface CustomRequestConfig extends AxiosRequestConfig {
  isMock?: boolean // 是否启用Mock
  retryCount?: number // 自动重试次数
  withToken?: boolean // 是否携带Token（默认true）
  errorHandler?: (error: unknown) => void // 自定义错误处理
}

class RequestClient {
  private instance: AxiosInstance
  private abortControllerMap: Map<string, AbortController>

  constructor(config: CustomRequestConfig = {}) {
    this.instance = this.createAxiosInstance(config)
    this.abortControllerMap = new Map()
    this.setupInterceptors()
  }

  // 创建基础实例
  private createAxiosInstance(config: CustomRequestConfig): AxiosInstance {
    console.log("VITE_API_BASE_URL:", import.meta.env.VITE_API_BASE_URL)
    return axios.create({
      baseURL: import.meta.env.VITE_API_BASE_URL || 'http://localhost:8000/',
      timeout: 15000,
      headers: {
        'Content-Type': 'application/json',
        ...config.headers
      },
      ...config
    })
  }

  // 设置拦截器
  private setupInterceptors() {
    // 请求拦截
    this.instance.interceptors.request.use(this.handleRequest.bind(this))

    // 响应拦截
    this.instance.interceptors.response.use(
      this.handleResponse.bind(this),
      this.handleError.bind(this)
    )
  }

  // 请求拦截处理
  private handleRequest(config: InternalAxiosRequestConfig): InternalAxiosRequestConfig {
    // 取消请求控制器
    const customConfig = config as InternalAxiosRequestConfig & CustomRequestConfig

    const controller = new AbortController()
    const urlKey = this.generateRequestKey(config)
    config.signal = controller.signal
    this.abortControllerMap.set(urlKey, controller)
    console.log("this.abortControllerMap:", this.abortControllerMap)
    // Token处理
    if (customConfig.withToken !== false) {
      const token = getStorage('token')
      if (token) {
        customConfig.headers.Authorization = `Bearer ${token}`
      }
    }

    // Mock模式处理
    if (customConfig.isMock) {
      customConfig.baseURL = import.meta.env.VITE_API_BASE_URL
        ? '/api/items/'
        : customConfig.baseURL
    }

    // 自动Content-Type处理
    if (customConfig.data instanceof FormData && !customConfig.headers['Content-Type']) {
      customConfig.headers['Content-Type'] = 'multipart/form-data'
    }

    return customConfig
  }


  // 生成唯一请求标识键
  private generateRequestKey(config: InternalAxiosRequestConfig): string {
    return `${config.method?.toUpperCase()}:${config.url}?${JSON.stringify(config.params)}`
  }

  // 成功响应处理
  private handleResponse(response: AxiosResponse<ResponseData>): AxiosResponse<ResponseData> {
    const urlKey = this.generateRequestKey(response.config)
    this.abortControllerMap.delete(urlKey)
    // 业务状态码检查
    if (response.data.code !== 200) {
      throw new AxiosError(
        response.data.message || '业务错误',
        'BUSINESS_ERROR',
        response.config,
        response.request,
        response
      )
    }

    return response
  }

  // 错误处理
  private handleError(error: unknown): Promise<never> {
    // 非Axios错误直接抛出
    if (!axios.isAxiosError(error)) {
      return Promise.reject(error)
    }

    const config = error.config as CustomRequestConfig & InternalAxiosRequestConfig;
    const urlKey = config ? this.generateRequestKey(config) : ''
    this.abortControllerMap.delete(urlKey)
    // 自定义错误处理器
    if (config?.errorHandler) {
      config.errorHandler(error)
      return Promise.reject(error)
    }

    // 统一错误处理
    if (error.response) {
      const { status, data } = error.response

      let errorMessage = error.message

      // 业务错误特殊处理
      if (error.code === 'BUSINESS_ERROR') {
        errorMessage = (data as ResponseData).message || '业务错误'
      } else {
        errorMessage = `请求错误：${status}`
      }

      // 状态码处理
      switch (status) {
        case 401:
          window.location.replace('/login')
          break
        case 403:
          console.warn('无权限操作:', error.config?.url)
          break
        case 500:
          console.error('服务器错误:', data)
          break
      }

      return Promise.reject(new Error(errorMessage))
    }

    // 请求未收到响应
    if (error.request) {
      return Promise.reject(new Error('网络连接异常'))
    }

    // 其他错误
    return Promise.reject(error)
  }

  // 核心请求方法
  public async request<T = unknown>(
    config: CustomRequestConfig
  ): Promise<ResponseData<T>> {
    try {
      const response = await this.instance.request<ResponseData<T>>(config)
      return response.data
    } catch (error) {
      // 自动重试逻辑
      if (config.retryCount && config.retryCount > 0) {
        return this.retryRequest<T>(config)
      }
      throw error
    }
  }

  // 快捷方法
  public get<T = unknown>(url: string, config?: CustomRequestConfig) {
    return this.request<T>({ ...config, method: 'GET', url })
  }

  public post<T = unknown>(url: string, data?: any, config?: CustomRequestConfig) {
    return this.request<T>({ ...config, method: 'POST', url, data })
  }

  // 取消请求
  public cancelRequest(urls: string | string[], method: string) {
    const targets = Array.isArray(urls) ? urls : [urls]
    targets.forEach(url => {
      const key = this.generateRequestKey({
        method: method,
        url,
        params: {},
        headers: {} as AxiosRequestHeaders
      })
      this.abortControllerMap.get(key)?.abort()
      this.abortControllerMap.delete(key)

      console.log("this.abortControllerMap.key:", key)
      console.log("this.abortControllerMap.key:", api.abortControllerMap)
    }
    )

   

  }

  // 重试请求逻辑
  private async retryRequest<T>(config: CustomRequestConfig): Promise<ResponseData<T>> {
    let retry = config.retryCount || 0
    const delay = (retryCount: number) => 1000 * (retryCount - retry + 1)

    while (retry > 0) {
      try {
        const response = await this.instance.request<ResponseData<T>>(config)
        return response.data
      } catch (error) {
        retry--
        if (retry === 0) throw error
        await new Promise(resolve => setTimeout(resolve, delay(retry)))
      }
    }

    return Promise.reject('重试失败')
  }
}

// 实例化请求客户端（单例模式）
export const api = new RequestClient({
  // 全局默认配置
  timeout: 15000,
  retryCount: 2,
  headers: {
    'X-Client-Version': '1.0.0'
  }
})

// URL拼接工具
export function urlJoin(domain: string, route: string): string {
  // 校验基础域名
  if (!domain || typeof domain !== 'string') {
    throw new Error('Invalid domain parameter')
  }

  // 标准化域名协议头
  if (!domain.startsWith('http://') && !domain.startsWith('https://')) {
    domain = `https://${domain}`
  }

  // 处理空路由
  if (!route) return domain

  // 处理空域名
  if (!domain) return route

  try {
    return new URL(route, domain).href
  } catch (error) {
    console.error('URL拼接失败:', { domain, route }, error)
    // 返回安全值
    return domain
  }
}